/*
 * main.c
 *
 *  Created on: 27.11.2011
 *      Author: alexs
 */

#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "stm32f10x_conf.h"
//#include <stdio.h>
#include <stdlib.h>
#include "prn_func.h"
#include <string.h>
#include "main.h"
#include "rfm23.h"

#define LED_ON GPIO_ResetBits(GPIOA,GPIO_Pin_8)
#define LED_OFF GPIO_SetBits(GPIOA,GPIO_Pin_8)
#define START_1msTIMER TIM_Cmd(TIM4,ENABLE)

const uint32_t arr26[]={CHIP26_0,CHIP26_1,CHIP26_2};
const uint32_t arr27[]={CHIP27_0,CHIP27_1,CHIP27_2};
uint32_t chip_SN[3];
uint8_t chip_tx=0;

char USART_TX_BUFF[USART_TX_BUFF_SIZE];
volatile uint16_t timeout_flag=0;
volatile uint16_t spi_read_flag=0;

//uint32_t psent=0;
//uint32_t perr=0;
//uint32_t pointerr=0;
char SPI1_DMA_BUFF_TX[17]={0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char SPI1_DMA_BUFF_RX[40];


volatile uint16_t tHigh;

void HW_init();
void master();
void slave();

uint8_t SPI_talk(SPI_dir dir, const uint8_t addr, const uint8_t val);

point_t points_arr[NUM_POINTS];

int main() {
	/*TODO убрать длинну пакета!!!!!*/

	RCC_ClocksTypeDef clocks;
	uint32_t * uid;

	HW_init();
	RCC_GetClocksFreq(&clocks);

	DBGstr("\r\nReset...\r\n");

	uid=(uint32_t *)(0x1FFFF7E8);
	chip_SN[2]=*(uid++);
	chip_SN[1]=*(uid++);
	chip_SN[0]=*uid;

	if (memcmp(chip_SN,arr27,sizeof(chip_SN))==0) {
		DBGstr("Slave chip\r\n");
	}
	else if (memcmp(chip_SN,arr26,sizeof(chip_SN))==0) {
		DBGstr("Master chip\r\n");
		chip_tx=1;
	}
	else {
		DBGstr("Chip unknown!\r\n");
		DBGulh("SN2 0x",chip_SN[2],"\r\n");
		DBGulh("SN1 0x",chip_SN[1],"\r\n");
		DBGulh("SN0 0x",chip_SN[0],"\r\n");
	}
	timeout_flag=50;
	START_1msTIMER;
	while (timeout_flag);
	SPI_talk(WRITE,RFM23_07_Operating_Mode_and_Function_Control_1,0x80);
	timeout_flag=50;
	START_1msTIMER;
	while (timeout_flag);

	RFM23_Init();
	RFM23_to_READY();
	DBGstr("\r\n");
	//	for (;;){
	if (chip_tx) {
		master();
	}else{
		slave();
	}
	//	}
	return 0;
}//main()

void HW_init(){
	GPIO_InitTypeDef gpio_init_stuct;
	USART_InitTypeDef usart_init_struct;
	USART_ClockInitTypeDef usartck_init_struct;
	DMA_InitTypeDef dma_init_struct;
	SPI_InitTypeDef spi_init_struct;
	TIM_TimeBaseInitTypeDef time_base_init_struct;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	RCC_APB2PeriphClockCmd(
			RCC_APB2Periph_AFIO|
			RCC_APB2Periph_GPIOA|
			RCC_APB2Periph_GPIOB|
			RCC_APB2Periph_USART1|
			RCC_APB2Periph_SPI1|
			RCC_APB2Periph_TIM1
			,ENABLE);
	RCC_APB1PeriphClockCmd(
			RCC_APB1Periph_USART2|
			RCC_APB1Periph_TIM4
			,ENABLE);

	NVIC_SetVectorTable(NVIC_VectTab_FLASH,0);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	/*Светодиод*/
	GPIO_SetBits(GPIOA,GPIO_Pin_8);
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_Out_OD;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_8;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*USART TX*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_AF_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_2;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*USART RX*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_3;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI: CLK MOSI NSS */
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_AF_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_7;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	GPIO_SetBits(GPIOA,GPIO_Pin_4);
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_Out_PP;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_4;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI MISO*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IPU;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_6;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpio_init_stuct);

	/*SPI nIRQ*/
	gpio_init_stuct.GPIO_Mode=GPIO_Mode_IPU;
	gpio_init_stuct.GPIO_Pin=GPIO_Pin_0;
	gpio_init_stuct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&gpio_init_stuct);

	/*GPIO lock configured bits*/
	GPIO_PinLockConfig(GPIOA,
			GPIO_Pin_2|
			GPIO_Pin_3|
			GPIO_Pin_4|
			GPIO_Pin_5|
			GPIO_Pin_6|
			GPIO_Pin_7|
			GPIO_Pin_8);

	/*USART*/
	//	USART_StructInit(&usart_init_struct);
	usart_init_struct.USART_BaudRate=921600UL;
	usart_init_struct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	usart_init_struct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	usart_init_struct.USART_Parity=USART_Parity_No;
	usart_init_struct.USART_StopBits=USART_StopBits_1;
	usart_init_struct.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART2,&usart_init_struct);
	USART_ClockStructInit(&usartck_init_struct);
	USART_ClockInit(USART2,&usartck_init_struct);


	/*DMA-USART*/
	dma_init_struct.DMA_MemoryBaseAddr=(uint32_t)USART_TX_BUFF;
	dma_init_struct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_init_struct.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_init_struct.DMA_Mode=DMA_Mode_Normal;
	dma_init_struct.DMA_BufferSize=0;
	dma_init_struct.DMA_DIR=DMA_DIR_PeripheralDST;
	dma_init_struct.DMA_M2M=DMA_M2M_Disable;
	dma_init_struct.DMA_Priority=DMA_Priority_High;
	dma_init_struct.DMA_PeripheralBaseAddr=USART2_BASE+0x04;
	dma_init_struct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_init_struct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_Init(USART2TXDMA,&dma_init_struct);
	DMA_ClearFlag(USART2TCFLAG);
	USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
	//	DMA_Cmd(DMA1_Channel7,ENABLE);
	USART_Cmd(USART2,ENABLE);

	/*SPI*/
	spi_init_struct.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;
	spi_init_struct.SPI_CPHA=SPI_CPHA_1Edge;
	spi_init_struct.SPI_CPOL=SPI_CPOL_Low;
	spi_init_struct.SPI_CRCPolynomial=7;
	spi_init_struct.SPI_DataSize=SPI_DataSize_16b;
	spi_init_struct.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	spi_init_struct.SPI_FirstBit=SPI_FirstBit_MSB;
	spi_init_struct.SPI_Mode=SPI_Mode_Master;
	spi_init_struct.SPI_NSS=SPI_NSS_Soft;
	SPI_Init(SPI1,&spi_init_struct);
	SPI_Cmd(SPI1,ENABLE);

	dma_init_struct.DMA_MemoryBaseAddr=(uint32_t)SPI1_DMA_BUFF_TX;
	dma_init_struct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_init_struct.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_init_struct.DMA_Mode=DMA_Mode_Normal;
	dma_init_struct.DMA_BufferSize=17;
	dma_init_struct.DMA_DIR=DMA_DIR_PeripheralDST;
	dma_init_struct.DMA_M2M=DMA_M2M_Disable;
	dma_init_struct.DMA_Priority=DMA_Priority_High;
	dma_init_struct.DMA_PeripheralBaseAddr=SPI1_BASE+0x0c;
	dma_init_struct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_init_struct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_Init(DMA1_Channel3,&dma_init_struct);
	DMA_ClearFlag(DMA1_FLAG_GL3);

	dma_init_struct.DMA_MemoryBaseAddr=(uint32_t)SPI1_DMA_BUFF_RX;
	dma_init_struct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
	dma_init_struct.DMA_MemoryInc=DMA_MemoryInc_Enable;
	dma_init_struct.DMA_Mode=DMA_Mode_Normal;
	dma_init_struct.DMA_BufferSize=16;
	dma_init_struct.DMA_DIR=DMA_DIR_PeripheralSRC;
	dma_init_struct.DMA_M2M=DMA_M2M_Disable;
	dma_init_struct.DMA_Priority=DMA_Priority_High;
	dma_init_struct.DMA_PeripheralBaseAddr=SPI1_BASE+0x0c;
	dma_init_struct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
	dma_init_struct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_Init(DMA1_Channel2,&dma_init_struct);
	DMA_ClearFlag(DMA1_FLAG_GL2);
//	SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);

	/*0.1 sec timer*/

	NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	time_base_init_struct.TIM_ClockDivision=TIM_CKD_DIV1;
	time_base_init_struct.TIM_CounterMode=TIM_CounterMode_Up;
	time_base_init_struct.TIM_Period=36000;
	time_base_init_struct.TIM_Prescaler=0;
	time_base_init_struct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM4,&time_base_init_struct);
	TIM_ARRPreloadConfig(TIM4,ENABLE);
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
	//	START_1msTIMER;

	/*Measure timer*/
	NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	time_base_init_struct.TIM_ClockDivision=TIM_CKD_DIV1;
	time_base_init_struct.TIM_CounterMode=TIM_CounterMode_Up;
	time_base_init_struct.TIM_Period=0xffff;
	time_base_init_struct.TIM_Prescaler=0;
	time_base_init_struct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM1,&time_base_init_struct);
	TIM_ARRPreloadConfig(TIM1,DISABLE);
	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);

}

void TIM4_IRQHandler(void) {
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	timeout_flag--;
	if (!timeout_flag) TIM_Cmd(TIM4,DISABLE);
}
void TIM1_UP_IRQHandler(void) {
	TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	tHigh++;
}

caddr_t _sbrk(int incr)
{
	extern char _ebss;
	static char *heap_end;
	char *prev_heap_end;

	if (heap_end == 0)
	{
		heap_end = &_ebss;
	}
	prev_heap_end = heap_end;

	char * stack = (char*) __get_MSP();
	if (heap_end + incr > stack)
	{
		//        _write(STDERR_FILENO, "Heap and stack collision\n", 25);
		errno = ENOMEM;
		return (caddr_t) -1;
		//abort ();
	}

	heap_end += incr;
	return (caddr_t) prev_heap_end;

}


void master() {
	static uint32_t time=1;
	uint8_t i,j;
	uint8_t * p8;

	while (1) {
		for (i=0;i<NUM_POINTS;i++) {
			points_arr[i].point_name=i+1;
			points_arr[i].current_point=0;
			points_arr[i].total_points=0;
			points_arr[i].reserved2=0;
			//		DBGuld("Name > ",points_arr[i].point_name,"");
			points_arr[i].point_time=time;
			//		DBGuld(" time > ",points_arr[i].point_time,"");
			points_arr[i].point_lat=rand();
			//		DBGuld(" lat > ",points_arr[i].point_lat,"");
			points_arr[i].point_lon=rand();
			//		DBGuld(" lon > ",points_arr[i].point_lon,"\r\n");
		}
		time++;
		TIM_SetCounter(TIM1,0);
		tHigh=0;
		TIM_Cmd(TIM1,ENABLE);
		LED_ON;
		for (j=0;j<NUM_POINTS;j++) {
			p8=(uint8_t *)&points_arr[j];
			RFM23_clear_tx();
			//		SPI_talk(WRITE,RFM23_3E_Packet_Length,POINTS_SIZE);
			for (i=0;i<POINTS_SIZE;i++) {
				RFM23_push(*p8);
				p8++;
			}
			RFM23_set_TXINT();
			RFM23_clear_intterrupt();
			RFM23_to_TX();
			while (NIRQ_stat());
			//		RFM23_to_READY(); /* NOT needed - auto return to READY mode */
			/*
		timeout_flag=5;
		START_1msTIMER;
		while (timeout_flag);
			 */
		}
		LED_OFF;
		TIM_Cmd(TIM1,DISABLE);
		DBGuld("\rTimer > ",((((uint32_t)tHigh)<<16)|TIM_GetCounter(TIM1))/72,"");
		timeout_flag=1000;
		START_1msTIMER;
		while (timeout_flag);
	}
}

void DMA1_Channel3_IRQHandler(void) {
	uint8_t i;

	if(DMA_GetITStatus(DMA1_IT_TC3)==SET) {
		DBGstr("Int \r\n");
		GPIO_SetBits(GPIOA,GPIO_Pin_4);
		DMA_Cmd(DMA1_Channel2,DISABLE);
		DMA_Cmd(DMA1_Channel3,DISABLE);
		spi_read_flag=1;
		LED_OFF;
		for (i=0;i<40;i++) {
			DBGuld("",i,"\t");
			DBGuld("",SPI1_DMA_BUFF_RX[i],"\r\n");
		}
	}
		DMA_ClearITPendingBit(DMA1_IT_TC3);

}


void slave(){

	SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx|SPI_I2S_DMAReq_Tx,ENABLE);
	RFM23_clear_rx();
	RFM23_to_RX();
	RFM23_set_RXINT();
	RFM23_clear_intterrupt();
	DMA_SetCurrDataCounter(DMA1_Channel2,16);
	DMA_SetCurrDataCounter(DMA1_Channel3,17);
	while (NIRQ_stat());
	GPIO_ResetBits(GPIOA,GPIO_Pin_4);
	DMA_Cmd(DMA1_Channel2,ENABLE);
	DMA_Cmd(DMA1_Channel3,ENABLE);
	LED_ON;
	DBGstr("Reading...\r\n");

}


/*
void slave() {
	point_t tmp_point;
	uint8_t i;
	uint8_t * p8;
	static uint32_t time=0;

	timeout_flag=200;

	while (1) {
		//		START_1msTIMER;
		RFM23_clear_rx();
		RFM23_to_RX();
		RFM23_set_RXINT();
		RFM23_clear_intterrupt();
		while (NIRQ_stat()) {
			if (!timeout_flag) break;
		}
		if (timeout_flag) {
			TIM_Cmd(TIM4,DISABLE);
			TIM_SetCounter(TIM4,0);
			LED_ON;
			p8=(uint8_t *)&tmp_point;
			for (i=0;i<(POINTS_SIZE);i++) {
				*p8=RFM23_pop();
				p8++;
			}
			memcpy(&points_arr[tmp_point.point_name-1],&tmp_point,sizeof(point_t));
			if (tmp_point.point_time>time) time=tmp_point.point_time;
			timeout_flag=200;
			START_1msTIMER;
		}else{
			timeout_flag=200;
			LED_OFF;
			for (i=0;i<NUM_POINTS;i++) {
				if (points_arr[i].point_time==time) {
					DBGuld("\033[1;33m",points_arr[i].point_time," ");
				}else{
					DBGuld("\033[1;31m",points_arr[i].point_time," ");
				}
			}
			DBGuld(" >> ",time,"\r\n");
		}
	}
}
*/
